package com.hexacta.hrs.web.struts.actions.projects;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.Predicate;
import org.apache.commons.lang.StringUtils;
import org.apache.struts2.interceptor.ServletRequestAware;
import org.apache.struts2.interceptor.SessionAware;
import org.apache.struts2.interceptor.validation.SkipValidation;
import org.vectrics.employee.Employee;

import com.hexacta.hrs.domain.exchange.Currency;
import com.hexacta.hrs.domain.exchange.Referring;
import com.hexacta.hrs.domain.staffing.Client;
import com.hexacta.hrs.domain.staffing.Project;
import com.hexacta.hrs.domain.staffing.project.ContractType;
import com.hexacta.hrs.service.staffing.ClientService;
import com.hexacta.hrs.service.staffing.ProjectService;
import com.hexacta.hrs.services.crud.CrudService;
import com.hexacta.hrs.services.employee.EmployeeService;
import com.hexacta.hrs.services.exchange.ReferringService;
import com.hexacta.hrs.web.struts.actions.CrudAbstractAction;
import com.opensymphony.xwork2.ActionContext;

public class ProjectAction extends CrudAbstractAction<Project> implements
		SessionAware, ServletRequestAware {

	private static final String FILTER = "filterProjects";
	private static final String CREATE_NEW = "createNew";

	private static final long serialVersionUID = -8545228851840917262L;
	private Boolean validated = Boolean.FALSE;

	private ProjectService projectService;
	private ClientService clientService;
	private EmployeeService employeeService;
	private ReferringService referringService;

	private Map session;

	private List<Project> projectList = new ArrayList<Project>();
	
	private HttpServletRequest request;
	
	private String selectedEmployeeId = "";
	private String selectedEmployeeName = "";
	private String selectedProjectForRemove = "";
	private String selectedProjectForEdit = "";
	private String selectedProjectId = "";
	private String selectedProjectName = "";
	private String selectedClientId = "";
	private String selectedClientName = "";
	private String description = "";
	private String selectedContractType = "";
	private String selectedCurrencyType = "";
	
	private String selectedPartners = "";

	private Date selectedStartDate;
	private Date selectedEndDate;

	/**
	 * Prepara los campos para crear un nuevo proyecto.
	 */
	@SkipValidation
	public String createNew() {
		this.setSelectedStartDate(Calendar.getInstance().getTime());
		setMappedRequest(CREATE_NEW);
		return SUCCESS;
	}

	/**
	 * Action que se encarga de mostrar los detalles de un proyecto previamente
	 * seleccionado.
	 */
	@SkipValidation
	public String viewDetails() {
		Long projectId = Long.parseLong(this.getSelectedProjectForEdit());
		Project project = this.getProjectService().searchById(projectId);

		this.setSelectedProjectId(project.getId().toString());
		this.setSelectedProjectName(project.getName());
		this.setSelectedEmployeeId(project.getEmployeeInCharge().getId()
				.toString());
		this.setSelectedEmployeeName(project.getEmployeeInCharge().getPerson()
				.getName());
		this.setSelectedClientId(project.getClient().getId().toString());
		this.setSelectedClientName(project.getClient().getName());
		this.setDescription(project.getDescription());
		if (project.getContractType() != null) {
			this.setSelectedContractType(project.getContractType().getString());
		}

		this.setSelectedStartDate(project.getDateStart().getTime());

		if (project.getDateEnd() != null) {
			this.setSelectedEndDate(project.getDateEnd().getTime());
		}

		setMappedRequest(CREATE_NEW);
		return SUCCESS;
	}

	/**
	 * Crea un nuevo proyecto con los valores ingresados en el formulario.cto.
	 */
	public String saveProject() {
		Project project = null;
		if (StringUtils.isEmpty(this.getSelectedProjectForEdit())) {
			project = new Project();
		} else {
			Long projectId = Long.parseLong(this.getSelectedProjectForEdit());
			project = this.getProjectService().searchById(projectId);
		}

		project.setName(this.getSelectedProjectName());
		project.setDescription(this.getDescription());

		Calendar startDate = Calendar.getInstance();
		startDate.setTime(this.getSelectedStartDate());
		project.setDateStart(startDate);

		if (this.getSelectedEndDate() != null) {
			Calendar endDate = Calendar.getInstance();
			endDate.setTime(this.getSelectedEndDate());
			project.setDateEnd(endDate);
		} else {
			project.setDateEnd(null);
		}

		if (this.getSelectedContractType() != null) {
			ContractType contractType = ContractType.getTypeForName(this
					.getSelectedContractType());
			project.setContractType(contractType);
		}
		
		if(this.getSelectedCurrencyType() != null && !this.getSelectedCurrencyType().equalsIgnoreCase("") ){
			Currency currency = Currency.valueOf(this.getSelectedCurrencyType());
			project.setCurrency(currency);
		}
		
		project.getReferrings().clear(); 
		for (Employee partner : getPartnerList()) {
			int position = selectedPartners.indexOf("p"+partner.getId().toString());
			if(position !=- 1){
				Referring referring = new Referring();
				
				referring.setPartner(partner);
				referring.setAbjudication(Double.valueOf(selectedPartners.substring(selectedPartners.indexOf(",a", position)+2,selectedPartners.indexOf("a,", position)) ));
				referring.setDefaultPartner(Boolean.valueOf(selectedPartners.substring(selectedPartners.indexOf(",d", position)+2,selectedPartners.indexOf("d;", position)) ));
				project.getReferrings().add(referring);
			}
			
		}
		
		Long employeeId = Long.parseLong(this.getSelectedEmployeeId());
		Employee employee = this.getEmployeeService().searchById(employeeId);
		project.setEmployeeInCharge(employee);

		Long clientId = Long.parseLong(this.getSelectedClientId());
		Client client = this.getClientService().searchById(clientId);
		project.setClient(client);

		this.getProjectService().save(project);

		this.resetAllAttributes();
		return this.filterProjects();
	}
	
	public String editProject() {
		Project project = null;
		if (StringUtils.isEmpty(this.getSelectedProjectId())) {
			project = new Project();
		} else {
			Long projectId = Long.parseLong(this.getSelectedProjectId());
			project = this.getProjectService().searchById(projectId);
		}

		project.setName(this.getSelectedProjectName());
		project.setDescription(this.getDescription());

		Calendar startDate = Calendar.getInstance();
		startDate.setTime(this.getSelectedStartDate());
		project.setDateStart(startDate);

		if (this.getSelectedEndDate() != null) {
			Calendar endDate = Calendar.getInstance();
			endDate.setTime(this.getSelectedEndDate());
			project.setDateEnd(endDate);
		} else {
			project.setDateEnd(null);
		}

		if (this.getSelectedContractType() != null) {
			ContractType contractType = ContractType.getTypeForName(this
					.getSelectedContractType());
			project.setContractType(contractType);
		}

		Long employeeId = Long.parseLong(this.getSelectedEmployeeId());
		Employee employee = this.getEmployeeService().searchById(employeeId);
		project.setEmployeeInCharge(employee);

		Long clientId = Long.parseLong(this.getSelectedClientId());
		Client client = this.getClientService().searchById(clientId);
		project.setClient(client);

		this.getProjectService().save(project);

		this.resetAllAttributes();
		return this.filterProjects();
	}
	
	public String validateSaveProject() {
		if (getValidated()) {// already validated and accepted the message
			return this.filterProjects();
		}

		Boolean error = Boolean.FALSE;

		if (StringUtils.isEmpty(this.getSelectedProjectName())) {
			error = Boolean.TRUE;
			addFieldError("projectName", "Project Name is required.");
		}

		if (StringUtils.isEmpty(this.getSelectedClientId())
				|| StringUtils.isEmpty(this.getSelectedClientName())) {
			error = Boolean.TRUE;
			addFieldError("client", "Client is required.");
		}

		if (StringUtils.isEmpty(this.getSelectedEmployeeId())
				|| StringUtils.isEmpty(this.getSelectedEmployeeName())) {
			error = Boolean.TRUE;
			addFieldError("employee",
					"Manager / Partner in Charge is required.");
		}

		if (this.getSelectedStartDate() == null) {
			error = Boolean.TRUE;
			addFieldError("startDate", "Start Date is required.");
		}

		// Valido la fecha de inicio.
		if ((this.getSelectedStartDate() != null)
				&& (this.getSelectedEndDate() != null)
				&& (this.getSelectedStartDate().compareTo(getSelectedEndDate()) > 0)) {
			error = Boolean.TRUE;
			addFieldError("endDate",
					"Verify the date period entered since it's incorrect.");
		}

		// Realizo acciones si alguno de los campos no cumple con la validacion.
		if (error) {
			setModel(null);
			setMappedRequest(CREATE_NEW);
			return INPUT;
		}

		setMappedRequest(CREATE_NEW);
		return SUCCESS;
	}

	@SkipValidation
	public String deleteProject() {

		Long projectId = Long.parseLong(this.getSelectedProjectForRemove());
		Project project = this.getProjectService().searchById(projectId);
		this.getProjectService().delete(project);

		this.resetAllAttributes();
		return this.filterProjects();
	}

	/**
	 * Filtra los clientes a mostrar.
	 */
	@SkipValidation
	public String filterProjects() {
		List<Project> projectsForFilter = this.getProjectService().findAll();

		if (StringUtils.isNotEmpty(this.getSelectedClientId()))
			CollectionUtils.filter(projectsForFilter, new Predicate() {
				@Override
				public boolean evaluate(Object object) {
					Project aProject = (Project) object;
					return aProject.getClient().getId().equals(
							Long.parseLong(getSelectedClientId()));
				}
			});

		if (StringUtils.isNotEmpty(this.getSelectedProjectId()))
			CollectionUtils.filter(projectsForFilter, new Predicate() {
				@Override
				public boolean evaluate(Object object) {
					Project aProject = (Project) object;
					return aProject.getId().equals(
							Long.parseLong(getSelectedProjectId()));
				}
			});

		if (StringUtils.isNotEmpty(this.getSelectedContractType()))
			CollectionUtils.filter(projectsForFilter, new Predicate() {
				@Override
				public boolean evaluate(Object object) {
					Project aProject = (Project) object;
					if (aProject.getContractType() == null) {
						return false;
					}
					return (aProject.getContractType().getString()
							.equalsIgnoreCase(getSelectedContractType()));
				}
			});
		
		if (StringUtils.isNotEmpty(this.getSelectedCurrencyType())){
			CollectionUtils.filter(projectsForFilter, new Predicate() {
				@Override
				public boolean evaluate(Object object) {
					Project aProject = (Project) object;
					if (aProject.getCurrency() == null) {
						return false;
					}
					return (aProject.getCurrency().getString()
							.equalsIgnoreCase(getSelectedCurrencyType()));
				}
			});
		}
			
		if (StringUtils.isNotEmpty(this.getSelectedEmployeeId()))
			CollectionUtils.filter(projectsForFilter, new Predicate() {
				@Override
				public boolean evaluate(Object object) {
					Project aProject = (Project) object;
					return aProject.getEmployeeInCharge().getId().equals(
							Long.parseLong(getSelectedEmployeeId()));
				}
			});
		setSelectedStartDate(Calendar.getInstance().getTime());
		this.setProjectList(projectsForFilter);

		setMappedRequest(FILTER);
		return SUCCESS;
	}

	private void resetAllAttributes() {
		this.setSelectedEmployeeId("");
		this.setSelectedEmployeeName("");
		this.setSelectedProjectId("");
		this.setSelectedProjectName("");
		this.setSelectedClientId("");
		this.setSelectedClientName("");
		this.setSelectedContractType("");
		this.setSelectedProjectForRemove("");
		this.setDescription("");
		this.setSelectedContractType("");

		this.setSelectedStartDate(null);
		this.setSelectedEndDate(null);
	}

	public List<Project> getAllProjectsList() {
		return (List<Project>) this.getProjectService().findAll();
	}

	public List<Client> getAllClientList() {
		return (List<Client>) this.getClientService().findAll();
	}

	// Carga una lista de empleados que sean o Socios o Gerentes de Proyecto.
	public List<Employee> getEmployeeList() {
		List<Employee> employees = (List<Employee>) this.getEmployeeService()
				.getAllCurrentEmployees();

//		CollectionUtils.filter(employees, new Predicate() {
//			@Override
//			public boolean evaluate(Object object) {
//				Employee employee = (Employee) object;
//				return (employee.getFunction().getCode().equals("GtePro") || employee
//						.getFunction().getCode().equals("Socio"));
//			}
//		});

		return employees;
	}
	
	public List<Employee> getPartnerList(){
		return this.getEmployeeService().getPartners();
	}

	@Override
	protected CrudService<Project> getCrudService() {
		return this.getProjectService();
	}

	@Override
	public void setSession(Map<String, Object> session) {
		this.session = session;
	}

	public Map getSession() {
		return session;
	}

	public void setProjectService(ProjectService projectService) {
		this.projectService = projectService;
	}

	public ProjectService getProjectService() {
		return projectService;
	}

	public void setClientService(ClientService clientService) {
		this.clientService = clientService;
	}

	public ClientService getClientService() {
		return clientService;
	}

	public EmployeeService getEmployeeService() {
		return employeeService;
	}

	public void setEmployeeService(EmployeeService employeeService) {
		this.employeeService = employeeService;
	}
	
	public ReferringService getReferringService() {
		return referringService;
	}

	public void setReferringService(ReferringService referringService) {
		this.referringService = referringService;
	}

	public List<Project> getProjectList() {
		return projectList;
	}

	public void setProjectList(List<Project> projectList) {
		this.projectList = projectList;
	}

	public String getSelectedEmployeeId() {
		return selectedEmployeeId;
	}

	public void setSelectedEmployeeId(String selectedEmployeeId) {
		this.selectedEmployeeId = selectedEmployeeId;
	}

	public String getSelectedEmployeeName() {
		return selectedEmployeeName;
	}

	public void setSelectedEmployeeName(String selectedEmployeeName) {
		this.selectedEmployeeName = selectedEmployeeName;
	}

	public String getSelectedClientId() {
		return selectedClientId;
	}

	public void setSelectedClientId(String selectedClientId) {
		this.selectedClientId = selectedClientId;
	}

	public void setSelectedProjectId(String selectedProjectId) {
		this.selectedProjectId = selectedProjectId;
	}

	public String getSelectedProjectId() {
		return selectedProjectId;
	}

	public void setSelectedProjectForRemove(String selectedProjectForRemove) {
		this.selectedProjectForRemove = selectedProjectForRemove;
	}

	public String getSelectedProjectForRemove() {
		return selectedProjectForRemove;
	}

	public void setSelectedProjectName(String selectedProjectName) {
		this.selectedProjectName = selectedProjectName;
	}

	public String getSelectedProjectName() {
		return selectedProjectName;
	}

	public void setSelectedClientName(String selectedClientName) {
		this.selectedClientName = selectedClientName;
	}

	public String getSelectedClientName() {
		return selectedClientName;
	}

	public void setSelectedContractType(String selectedContractType) {
		this.selectedContractType = selectedContractType;
	}

	public String getSelectedContractType() {
		return selectedContractType;
	}

	public void setSelectedStartDate(Date selectedStartDate) {
		this.selectedStartDate = selectedStartDate;
	}

	public Date getSelectedStartDate() {
		return selectedStartDate;
	}

	public void setSelectedEndDate(Date selectedEndDate) {
		this.selectedEndDate = selectedEndDate;
	}

	public Date getSelectedEndDate() {
		return selectedEndDate;
	}

	public void setSelectedProjectForEdit(String selectedProjectForDetails) {
		this.selectedProjectForEdit = selectedProjectForDetails;
	}

	public String getSelectedProjectForEdit() {
		return selectedProjectForEdit;
	}

	public void setDescription(String description) {
		this.description = description;
	}

	public String getDescription() {
		return description;
	}

	public void setValidated(Boolean validated) {
		this.validated = validated;
	}

	public Boolean getValidated() {
		return validated;
	}
	
	public String getSelectedCurrencyType() {
		return selectedCurrencyType;
	}

	public void setSelectedCurrencyType(String selectedCurrencyType) {
		this.selectedCurrencyType = selectedCurrencyType;
	}

	public String getSelectedPartners() {
		return selectedPartners;
	}

	public void setSelectedPartners(String selectedPartners) {
		this.selectedPartners = selectedPartners;
	}

	public List<ContractType> getContractTypeList() {
		List<ContractType> list = new ArrayList<ContractType>();
		for (ContractType type : ContractType.values()) {
			list.add(type);
		}
		return list;
	}
	
	public List<Currency> getCurrencyList(){
		List<Currency> list = new ArrayList<Currency>();
		
		for (Currency currency : Currency.values()) {
			list.add(currency);
		}
		return list;
	}
}
